package com.cherrypt.api.core.service.impl;

import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.core.conditions.update.UpdateWrapper;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.cherrypt.api.common.enums.ResultEnum;
import com.cherrypt.api.common.enums.UserLoginEnum;
import com.cherrypt.api.common.exception.TipException;
import com.cherrypt.api.core.dao.UserLoginDao;
import com.cherrypt.api.model.dataobject.UserLogin;
import com.cherrypt.api.core.service.UserLoginService;
import com.cherrypt.api.common.util.CheckUtils;
import com.cherrypt.api.core.util.CherryUtils;
import org.apache.commons.codec.digest.DigestUtils;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.data.redis.core.StringRedisTemplate;
import org.springframework.data.redis.core.ValueOperations;
import org.springframework.stereotype.Service;

import java.time.Duration;

/**
 * @author intent
 * @date 2019/7/14 16:31
 * @about <link href='http://zzyitj.xyz/'/>
 */
@Service
public class UserLoginServiceImpl extends ServiceImpl<UserLoginDao, UserLogin> implements UserLoginService {
    private static final Logger logger = LoggerFactory.getLogger(UserLoginServiceImpl.class);

    @Autowired
    private StringRedisTemplate redisTemplate;

    @Autowired
    private ValueOperations<String, Object> valueOperations;

    @Value("${api.config.redis.userLogin.prefix}")
    private String userLoginPrefix;

    @Value("${api.config.redis.userLogin.exp}")
    private long userLoginExp;

    @Override
    public UserLogin getRedisUserLoginByUid(int uid) {
        return (UserLogin) valueOperations.get(userLoginPrefix + uid);
    }

    @Override
    public void saveRedisUserLogin(UserLogin userLogin) {
        valueOperations.set(userLoginPrefix + userLogin.getId(), userLogin, Duration.ofSeconds(userLoginExp));
    }

    @Override
    public boolean removeRedisUserLoginByUid(int uid) {
        Boolean delete = redisTemplate.delete(userLoginPrefix + uid);
        if (delete != null) {
            return delete;
        }
        return false;
    }

    @Override
    public boolean saveUserLogin(UserLogin userLogin) {
        return this.save(userLogin);
    }

    @Override
    public UserLogin getUserLoginByUid(int uid) throws TipException {
        // 先从Redis中查询
        UserLogin userLogin = getRedisUserLoginByUid(uid);
        // Redis中没有只有从数据库中查询
        if (userLogin == null) {
            userLogin = this.getById(uid);
            // 把userInfo存储在redis中
            if (userLogin == null) {
                throw new TipException(ResultEnum.USER_EMPTY_ERROR);
            }
            saveRedisUserLogin(userLogin);
            logger.info("缓存UserLogin到Redis: {}", userLogin);
        }
        return userLogin;
    }

    @Override
    public UserLogin getUserLoginByEmail(String email) throws TipException {
        return this.getOne(new QueryWrapper<UserLogin>().eq("email", email));
    }

    /**
     * 先检查redis中是否有该用户
     * 有则立即返回
     *
     * @param email
     * @param password
     * @return
     * @throws TipException
     */
    @Override
    public UserLogin login(String email, String password) throws TipException {
        UserLogin userLogin = this.getOne(new QueryWrapper<UserLogin>()
                .eq("email", email)
                .eq("password", DigestUtils.md5Hex(CherryUtils.config.getPassPrefix() + password)));
        if (userLogin == null) {
            throw new TipException(ResultEnum.LOGIN_ERROR);
        } else if (userLogin.getStatus() == UserLoginEnum.ACTIVE.getCode()) {
            return userLogin;
        } else if (userLogin.getStatus() == UserLoginEnum.NO_ACTIVE.getCode()) {
            throw new TipException(ResultEnum.ACTIVATION_ERROR);
        } else if (userLogin.getStatus() == UserLoginEnum.BAN.getCode()) {
            throw new TipException(ResultEnum.ACCOUNT_BAN_ERROR);
        }
        throw new TipException(ResultEnum.LOGIN_ERROR);
    }

    @Override
    public boolean activeUserLogin(String email) {
        UserLogin userLogin = new UserLogin();
        userLogin.setStatus(UserLoginEnum.ACTIVE.getCode());
        return this.update(userLogin, new UpdateWrapper<UserLogin>().eq("email", email));
    }

    @Override
    public boolean resetPass(String email, String password) throws TipException {
        UserLogin userLogin = new UserLogin();
        CheckUtils.checkPassword(password);
        userLogin.setPassword(DigestUtils.md5Hex(CherryUtils.config.getPassPrefix() + password));
        return this.update(userLogin, new UpdateWrapper<UserLogin>().eq("email", email));
    }

    @Override
    public boolean updateStatusByUid(int uid, UserLoginEnum userLoginEnum) {
        return updateStatusByUid(uid, userLoginEnum.getCode());
    }

    @Override
    public boolean updateStatusByUid(int uid, int code) {
        UserLogin userLogin = new UserLogin();
        userLogin.setStatus(code);
        if (this.update(userLogin, new UpdateWrapper<UserLogin>().eq("id", uid))) {
            return removeRedisUserLoginByUid(uid);
        }
        return false;
    }
}
